//
// Created by suzhen on 18-1-16.
//

#include <hacks/net/tcp_server.h>

namespace hacks::net {

    tcp_server::tcp_server(const ip_addr &addr,
                           const std::string &server_name)
            : loop_(nullptr),
              shd_acceptor_(nullptr),
              conn_map_(),
              s_server_name_(server_name),
              conn_id_flag_(0) {
        loop_ = mk_ev_loop();
        shd_acceptor_ = std::make_shared<tcp_acceptor>(loop_, addr);
        shd_acceptor_->set_accept_callback(std::bind(&tcp_server::on_new_connection, this, std::placeholders::_1));
    }

    void tcp_server::start() {
        std::thread th([this]() {
            loop_->run_loop(mode_default);
        });
        th.detach();
    }

    void tcp_server::on_new_connection(ev_os_sock_t incoming_fd) {
        constexpr auto conn_max_flag = std::numeric_limits<std::size_t>::max();
        if (conn_id_flag_ == conn_max_flag) {
            conn_id_flag_ = 0;
        }
        auto current_conn_flag = ++conn_id_flag_;
        auto time_now = std::chrono::system_clock::now();
        auto time_stamp = time_now.time_since_epoch().count();
        char buff[50]{0};
        sprintf(buff, "flag=%lu,time=%lu", current_conn_flag, time_stamp);
        std::string s_conn_flag(buff);
        auto new_tcp_conn = std::make_shared<tcp_conn>(loop_, incoming_fd);
        auto insert_result = conn_map_.insert(std::pair<std::string,
                shared_tcp_conn>(s_conn_flag, new_tcp_conn));
        //call accepted
        new_tcp_conn->on_accepted();
        //must insert success!
        assert(insert_result.second);
    }

}